#!/bin/bash
########################################################################
####  Script Name: sm-lib-kernel-install
####  version: 2.12.13
####  Date: 2014-11-18

####  Copyright (C) Harald Hope 2005-2014
####  The following functions use core logic by Kel Modderman (kelmo)
####  extra_module_installer update_kernel_links install_the_apt_kernel_module
####  install_apt_kernel_modules
####  This program is free software; you can redistribute it and/or modify it under
####  the terms of the GNU General Public License as published by the Free Software
####  Foundation; either version 2 of the License, or (at your option) any later version.

####  This program is distributed in the hope that it will be useful, but WITHOUT
####  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
####  FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

####  Get the full text of the GPL here:
####  http://www.gnu.org/licenses/old-licenses/gpl-2.0.html

####  Script Author: Harald Hope
####  This is a library file for smxi and cannot be run independently

####  Script URL: http://smxi.org/sm/sm-lib-kernel-install
####  Script SVN: http://code.google.com/p/smxi
####  Script Home page: http://techpatterns.com/forums/about736.html
####  FEATURES:
####  Script will install any number of kernels contained in a list of kernels
####  passed to it as parameters. This script will not run by itself.
####  This script is meant to be run as a module of smxi only
########################################################################

###---------------------------------------------------------------------
### kernel install advanced/double check questions
###---------------------------------------------------------------------

# allows user to select which kernel for their system to install
# 32 or 64 bit is selected automatically, otherwise the user can do what they want
alternate_kernel_install()
{
	eval $LOGPS
	local kernel='' options='' opt='' userSelection=''
	local text_1='' text_2=''  rcMessage='' repeat=''
	local optionList='' listCount='' kernelCount=''
	local altKernOpt1='' altKernelOption1='' altKernelText1=''
	local altKernOpt2='' altKernelOption2='' altKernelText2=''
	local altKernOpt3='' altKernelOption3='' altKernelText3=''
	local altKernOpt4='' altKernelOption4='' altKernelText4=''
	local altKernOpt5='' altKernelOption5='' altKernelText5=''
	local altKernOpt6='' altKernelOption6='' altKernelText6=''

	# set to use proper advanced kernel data 64 / 32 bit
	# no need to load this data more than once per run through.

	if [ "$B_KERNEL_DATA_SET" != 'true' ];then
		set_kernel_data
		B_KERNEL_DATA_SET='true'
	fi
	# add the list closer items
	kernelCount=$( wc -w <<< $KERNEL_LIST )
	optionList="$KERNEL_LIST "
	if [ "$B_USE_DEBIAN_KERNEL" == 'true' ];then
		altKernelOption1='install-debian-kernel'
		altKernelText1='Debian'
		if [ "$BITS" == '32' ];then
			if [ -z "$( grep -E '^(2\.6|[3-9]).*-486$' <<< $CURRENT_KERNEL )" ];then
				altKernelOption4='install-debian-486-kernel'
				altKernelText4='Debian-486'
			else
				altKernelOption5='install-debian-686-kernel'
				altKernelText5='Debian-686'
			fi
		fi
	fi
	optionList="$optionList $altKernelOption1"
	altKernOpt1=$( wc -w <<< $optionList )
	optionList="$optionList $altKernelOption4"
	altKernOpt4=$( wc -w <<< $optionList )
	optionList="$optionList $altKernelOption5"
	altKernOpt5=$( wc -w <<< $optionList )
	
	if [ "$B_SIDUCTION_SOURCES" == 'true' ];then
		altKernelOption2='install-siduction-kernel'
		altKernelText2='siduction'
	elif [ "$B_APTOSID_SOURCES" == 'true' ];then
		altKernelOption2='install-aptosid-kernel'
		altKernelText2='aptosid'
	fi
	optionList="$optionList $altKernelOption2"
	altKernOpt2=$( wc -w <<< $optionList )

	# this works but mepis has no kernel metapackage to test so will always fail
	if [ "$B_MEPIS_SOURCES" == 'true' ];then
		altKernelOption3='install-mepis-kernel'
		altKernelText3='Mepis'
	fi
	optionList="$optionList $altKernelOption3"
	altKernOpt3=$( wc -w <<< $optionList )

	if [ "$B_LIQUORIX_SOURCES" == 'true' ];then
		altKernelOption6='install-liquorix-kernel'
		altKernelText6='Liquorix'
	fi
	optionList="$optionList $altKernelOption6"
	altKernOpt6=$( wc -w <<< $optionList )

	optionList="$optionList back-to-main-menu"

	listCount=$( wc -w <<< $optionList )

	local bmmOption=$listCount

	print_lib_info $LIB_KERNEL_INSTALL
	echo $MLINE
	echo "${M}NOTE: The listed kernels are zip files of ${C}$BITS bit${M} kernel debs plus installer script."
	if [[ "$BITS" == '32' ]];then
		if [ "$( check_pae_support )" == 'true' ];then
			echo "These are the ${C}PAE${S} kernels for your ${C}PAE CPU${S}."
			echo "${C}PAE${S} means CPU supports ${C}> 3.2 GB${S} of ram (3.6 and earlier not PAE)."
		else
			echo "These are the ${C}Non PAE${S} kernels for your ${C}Non PAE CPU${S}."
			echo "(This means your CPU supports ${C}max 3.2 GB${S} of ram.)"
		fi
	fi
	echo "For current, standard apt kernel install, RETURN TO MAIN MENU!!"
	echo "${C}1-$kernelCount - Archived kernel zip files${S} Will install the kernel you select."
	echo "       ${C}liquorix${S} kernels: zen kernel sources; desktop performance by damentz."
	echo
	print_alt_kernel_option "$altKernelOption1" "$altKernOpt1" "$altKernelText1"
	print_alt_kernel_option "$altKernelOption4" "$altKernOpt4" "$altKernelText4"
	print_alt_kernel_option "$altKernelOption5" "$altKernOpt5" "$altKernelText5"
	print_alt_kernel_option "$altKernelOption2" "$altKernOpt2" "$altKernelText2"
	print_alt_kernel_option "$altKernelOption3" "$altKernOpt3" "$altKernelText3"
	print_alt_kernel_option "$altKernelOption6" "$altKernOpt6" "$altKernelText6"
	
	echo "${C}$bmmOption - back-to-main-menu${S} Returns you to the main menu."
	echo
	echo "${Q}Please enter in the correct number for the kernel or option you want."
	echo $LINE

	# this was set to correct 64/32 list in set_64_32 function
	options=$optionList

	select opt in $options
	do
		for kernel in $optionList
		do
			if [ "$opt" == "$kernel" ];then
				case $kernel in
					back-to-main-menu)
						# this is required to reset the old kernel file
						# KERNEL_FILE_RESET is set in set_32_64_bit
						KERNEL_FILE=$KERNEL_FILE_RESET
						;;
					install-debian-kernel|install-debian-486-kernel|install-debian-686-kernel|install-liquorix-kernel|install-mepis-kernel|install-aptosid-kernel|install-siduction-kernel)
						:
						;;
					*)
						KERNEL_FILE=$kernel
						;;
				esac
				userSelection=$kernel
				break
			fi
		done

		break
	done
	eval $LOGPE
	case "$userSelection" in
		# handle null case first
		'')
			print_error opt
			repeat='true'
			;;
		back-to-main-menu)
			kernel_options
			;;
		install-debian-kernel)
			get_current_apt_kernel debian
			double_check_kernel apt-debian
			;;
		install-debian-486-kernel)
			get_current_apt_kernel debian-486
			double_check_kernel apt-debian-486
			;;
		install-debian-686-kernel)
			get_current_apt_kernel debian-686
			double_check_kernel apt-debian-686
			;;
		install-liquorix-kernel)
			get_current_apt_kernel liquorix
			double_check_kernel apt-liquorix
			;;
		install-mepis-kernel)
			get_current_apt_kernel mepis
			double_check_kernel apt-mepis
			;;
		install-aptosid-kernel)
			get_current_apt_kernel aptosid
			double_check_kernel apt-aptosid
			;;
		install-siduction-kernel)
			get_current_apt_kernel siduction
			double_check_kernel apt-siduction
			;;
		# any archived kernels here
		*-amd64|*-686*)
			double_check_kernel advanced
			;;
		*)
			print_error opt
			repeat='true'
			;;
	esac
	if [ "$repeat" == 'true' ];then
		alternate_kernel_install
	fi
}

# args: $1 - altKernelOptionx; $2 - $altKernOptx; $3 - $altKernelTextx
print_alt_kernel_option()
{
	eval $LOGUS
	local debianExtraText=''
	if [ -n "$1" ];then
		if [ "$1" == 'install-debian-kernel' ];then
			debianExtraText=' (type matches your running kernel),'
		fi
		echo "${C}$2 - $1${S} Installs current ${C}$3${S} kernel$debianExtraText"
		echo "     as well as any required ${C}$3${S} kernel modules available in apt."
		echo "     Note: you will see which specific ${C}$3${S} kernel will be installed in the next step, "
		echo "     and can skip the install if you don't want it."
		if [ "$1" == 'install-debian-686-kernel' ];then
			echo "     ${M}Debian ${C}686${M} kernels only work on ${C}Pentium 3${M} or newer cpu types."
		fi
	fi
	eval $LOGUE
}

# args: $1 - advanced/apt/apt-debian
double_check_kernel()
{
	eval $LOGPS
	local repeat='' options='' opt='' kernelFile='' extraText=''

	check_debian_kernel_version
	case $1 in
		# handles default system cases
		apt)
			kernelFile="$CURRENT_APT_KERNEL"
			extraText="current $DEFAULT_KERNEL"
			;;
		apt-debian)
			kernelFile="$CURRENT_DEBIAN_KERNEL"
			extraText='current Debian'
			;;
		apt-debian-486)
			kernelFile="$CURRENT_DEBIAN_KERNEL"
			extraText='current Debian-486'
			;;
		apt-debian-686)
			kernelFile="$CURRENT_DEBIAN_KERNEL"
			extraText='current Debian-686'
			;;
		apt-liquorix)
			kernelFile="$CURRENT_LIQUORIX_KERNEL"
			extraText='current Liquorix'
			;;
		apt-mepis)
			kernelFile="$CURRENT_MEPIS_KERNEL"
			extraText='current Mepis'
			;;
		apt-aptosid)
			kernelFile="$CURRENT_APTOSID_KERNEL"
			extraText='current aptosid'
			;;
		apt-siduction)
			kernelFile="$CURRENT_SIDUCTION_KERNEL"
			extraText='current siduction'
			;;
		advanced)
			kernelFile=$KERNEL_FILE
			extraText='zip archived'
			;;
	esac

	log_function_data "Kernel Install Selection: $extraText $kernelFile"

	if [ -n "$kernelFile" ];then
		echo $LINE
		echo "${S}You will be installing the ${C}$extraText${S} kernel: ${C}$kernelFile$DEBIAN_KERNEL_CANDIDATE${S}"
		echo "${Q}Is this correct?"
		echo $LINE
		echo "${C}1${S} - Yes, install this kernel now."
		echo "${C}2${S} - No, let me go back to the menu to make a new selection."
		echo "${C}3${S} - Continue with the $DU_UPGRADE without installing a new kernel."
		echo $LINE
		echo $SLE
		echo $LINE

		options="yes-install-kernel no-return-to-menu continue-no-kernel"

		select opt in $options
		do
			case $opt in
				yes-install-kernel)
					echo "${S}OK, now the script will install kernel ${C}$kernelFile${S} for you.${N}"
					eval $LOGPE
					case $1 in
						apt)
							install_apt_kernel $DEFAULT_KERNEL
							;;
						apt-debian|apt-debian-486|apt-debian-686)
							install_apt_kernel debian
							;;
						apt-liquorix)
							install_apt_kernel liquorix
							;;
						apt-mepis)
							install_apt_kernel mepis
							;;
						apt-aptosid)
							install_apt_kernel aptosid
							;;
						apt-siduction)
							install_apt_kernel siduction
							;;
						advanced)
							install_kernel_zip
							echo $LINE
							;;
					esac
					;;
				no-return-to-menu)
					echo "${S}Ok, let's try it again, please make your selection.${N}"
					eval $LOGPE
					kernel_return_location $1
					;;
				continue-no-kernel)
					echo "${S}OK, continuing with script without installing new kernel."
					eval $LOGPE
					;;
				*)
					print_error opt
					repeat='true'
					;;
			esac
			break
		done
		if [ "$repeat" == 'true' ];then
			eval $LOGPE
			double_check_kernel $1
		fi
	else
		eval $LOGPE
		error_handler 'null-kernel-file-data' "$FUNCNAME" "$1"
		print_hec
		kernel_return_location $1
	fi
}
# args: $1 - the arg for kernel confirm question
kernel_return_location()
{
	case $1 in
		advanced|apt-debian|apt-debian-686|apt-debian-486|apt-liquorix|apt-mepis|apt-aptosid|apt-siduction)
			alternate_kernel_install
			;;
		*)
			kernel_options
			;;
	esac
}
# kernel_options
#check_kernel

###---------------------------------------------------------------------
### kernel install using apt
###---------------------------------------------------------------------

# args: $1 - package to test for
kernel_authentication_handler()
{
	eval $LOGUS
	local liquorixKeyrings='liquorix-keyrings'
	local siductionKeyrings='siduction-archive-keyring'
	
	case $1 in
		liquorix)
			if [ -z "$( package_tester "$liquorixKeyrings" )" ];then
				package_installer "$liquorixKeyrings liquorix-keyring" 'install-missing' '--allow-unauthenticated -y'
			fi
			;;
		siduction)
			if [ -z "$( package_tester "$siductionKeyrings" )" ];then
				package_installer "$siductionKeyrings" 'install-missing' '--allow-unauthenticated -y'
			fi
			;;
	esac

	eval $LOGUE
}

# master apt kernel installer function
# args: $1 debian/aptosid/siduction/liquorix
install_apt_kernel()
{
	eval $LOGPS
	local currentAptKernel=''

	case "$1" in
		debian)
			currentAptKernel=$CURRENT_DEBIAN_KERNEL
			;;
		liquorix)
			currentAptKernel=$CURRENT_LIQUORIX_KERNEL
			libata_devicemap_fix_1
			;;
		mepis)
			currentAptKernel=$CURRENT_MEPIS_KERNEL
			;;
		aptosid)
			currentAptKernel=$CURRENT_APTOSID_KERNEL
			libata_devicemap_fix_1
			;;
		siduction)
			currentAptKernel=$CURRENT_SIDUCTION_KERNEL
			libata_devicemap_fix_1
			;;
	esac
	# this is set top of smxi file, to make turning off this feature easier.
	if [ "$B_LIBC6_BORKED" != 'true' ];then
		libc6_fix_1 'kernel'
	fi
	backup_grub
	install_the_apt_kernel $currentAptKernel
	update_kernel_links $currentAptKernel # must run prior to update_grub
	update_grub
	case "$1" in
		liquorix)
			: # no module debs currently
			;;
		*)
			install_apt_kernel_modules 'standard' $currentAptKernel "$noAuthent"
			;;
	esac
	case "$1" in
		debian|mepis|aptosid|siduction)
			extra_module_installer $currentAptKernel 'madwifi'
			;;
	esac
	case "$1" in
		debian|mepis|liquorix)
			extra_module_installer $currentAptKernel 'ndiswrapper'
			;;
	esac
	create_kernel_install_directory $currentAptKernel
	case "$1" in
		liquorix|aptosid|siduction|debian)
			: # no module debs currently
			;;
		*)
			download_remaining_module_debs $currentAptKernel "$noAuthent"
			;;
	esac
	copy_debs_to_install_directory $currentAptKernel
	post_install_messages
	reboot_now_question $currentAptKernel
	eval $LOGPE
}

# the actual first step install
# args: $1 - kernel version to install
install_the_apt_kernel()
{
	eval $LOGUS
	local kernelImage="linux-image-$1"
	local kernelHeaders="linux-headers-$1"
	# add alt kernel keyrings if needed
	kernel_authentication_handler $1 
	echo $LINE
	echo "${S}Installing your new ${C}$1${S} kernel now...${N}"
	package_installer "$kernelHeaders $kernelImage" 'install-always' 
	eval $LOGUE
}

# now loop through and install all running modules for new kernel
# args: $1 - type standard/meta; $2 - kernel version to install, only for standard
# add: tp-smapi- r5u870- eeepc-acpi- qc-usb- sfc- rfswitch-
install_apt_kernel_modules()
{
	eval $LOGUS
	local supportedModules='acer_acpi acerhk acx atl2 aufs av5100 btrfs drbd8 eeepc_acpi em8300 et131x fsam7400 gspca kqemu lirc_modules lirc loop_aes lzma ndiswrapper nilfs omnibook qc_usb quickcam r5u870 r6040 rfswitch rt73 sfc speakup sqlzma squashfs tp_smapi vboxadd vboxdrv'
	local module='' modulePath='' modulePackage='' moduleType='' kernelArch='686'
	local extraModuleText=''
	if [ "$BITS" == '64' ];then
		kernelArch='amd64'
	fi
	# note, need to wait for liquorix to switch, debian will require special handling
	# because of 2.6 in squeeze and older
	case $1 in
		standard)
			moduleType=$2
			;;
		meta-liquorix)
			if [ -n "$( check_package_status "linux-image-liquorix-$kernelArch"  'c' )" ];then
				moduleType="liquorix-$kernelArch"
			else
				moduleType="$CURRENT_APT_KERN_BASE-liquorix-$kernelArch"
			fi
			extraModuleText=' meta package'
			;;
		meta-aptosid)
			moduleType="aptosid-$kernelArch"
			extraModuleText=' meta package'
			;;
		meta-siduction)
			moduleType="siduction-$kernelArch"
			extraModuleText=' meta package'
			;;
		meta-debian)
			if [ -n "$( check_package_status "linux-image-$kernelArch"  'c' )" ];then
				moduleType="$kernelArch"
			else
				moduleType="$CURRENT_APT_KERN_BASE-$kernelArch"
			fi
			extraModuleText=' meta package'
			;;
		*)
			error_handler 'value-bad' $FUNCNAME "$1"
			;;
	esac

	echo $LINE
	echo "${S}Checking for ${C}$moduleType$extraModuleText${S} kernel modules in apt now....${N}"
	# try to install external module packages
	for module in $supportedModules
	do
		modulePath="$(/sbin/modinfo -k $(uname -r) -F filename "${module}" 2>/dev/null)"

		if [ -n "${modulePath}" ];then
			log_function_data "module: $module"
			log_function_data "modulePath: $modulePath"
			#echo "${SPACER}${S}module path: ${C}$modulePath${N}"
			modulePackage="$( dpkg -S ${modulePath} 2>/dev/null | grep -iv 'linux-image-' )"
			log_function_data "modulePackage: $modulePackage"
			# if the module has been merged into the kernel, we need to not try to install
			# or the installer will try to install linux-image...
			if [ -n "$modulePackage" ];then
				#echo "${SPACER}${S}module package a: ${C}$modulePackage${N}"
				# now we pull out the actual module name we will test for in the installer
				modulePackage="$( echo $modulePackage | sed s/$(uname -r).*/${moduleType}/g )"
				install_the_apt_kernel_module "$modulePackage" 'auto'
			fi
		fi
	done
	eval $LOGUE
}

# args: $1 - module package name; $2 - triggered from auto/manual mode;
install_the_apt_kernel_module()
{
	eval $LOGUS
	local modulePackage=$1
	local noModuleText=''
	local moduleExists=$( grep-aptavail -PX "$modulePackage" )
	local moduleOutputName=$( grep -Eo '.*-modules' <<< $modulePackage )
	# add alt kernel keyrings if needed
	kernel_authentication_handler $1

	case $2 in
		manual)
			noModuleText='The module you are attempting to install'
			;;
		auto)
			noModuleText='Your previously installed module'
			;;
	esac

	# if grep-aptavail -PX "$modulePackage" >/dev/null 2>&1
	if [ -n "$moduleExists" ];then
		#echo "${SPACER}${S}Checkinging kernel module: ${C}$modulePackage${N}"
		package_installer "$modulePackage" 'install-always' 
		if [ "$?" -ne 0 ];then
			$APT_TYPE -f install
		else
			# ignore error cases for now, apt will do the "right" thing to get
			# into a consistent state and worst that could happen is some external
			# module not getting installed
			:
		fi
	else
		echo
		echo "$SPACER${M}$noModuleText: ${C}$moduleOutputName${M} is  not in apt currently.${N}"
	fi
	eval $LOGUE
}

# this will sync the kernel download directory module debs with the aptosid ones.
# to come: using the user set mirror?
# args: $1 - kernel name
download_remaining_module_debs()
{
	eval $LOGUS
	# not current: acx100- redhat-cluster-modules- loop-aes-modules-
	local module='' missingModules='' missingModule=''
	local availableModules="$( print_module_list )"
	# add alt keyrings if needed
	kernel_authentication_handler $1

	echo $LINE
	echo "${S}Downloading missing modules from aptosid repos to kernel install directory (can take a few seconds)...${N}"

	for module in $availableModules
	do
		echo -n "${SPACER}${S}Checking for ${C}$module$1${S} now...${N}"
		moduleError=''
		# note: $APT_TYPE using apt-get to avoid aptitude deciding to install these during du
		apt-get install -d -y $module$1 &> /dev/null || moduleError='true'
		if [ "$moduleError" == 'true' ];then
			missingModules="$missingModules $module$1"
			echo "${SPACER}${SPACER}${M}Module not available${N}"
		else
			echo "${SPACER}${SPACER}${S}Download successful${N}"
		fi
	done
	echo
	if [ -z "$missingModules" ];then
		echo "${S}Kernel/module debs downloaded successfully.${N}"
	else
		echo "${M}Not all module deb files downloaded/synced successfully.${N}"
# 		for missingModule in $missingModules
# 		do
# 			echo ${C}$missingModule${N}
# 		done
		echo "${S}This is not that important, not all modules are available always.${N}"
	fi
	eval $LOGUE
}

# copy over all installed kernel debs to kernel download directory
# args: $1 - kernel version
copy_debs_to_install_directory()
{
	eval $LOGUS
	# this handles both 2.6.24-2.6.24-3 and 2.6.25-3 syntax
	local kernelBase=$( echo $1 | cut -d '-' -f 1-2 )
	local installDirectory="$SM_KERNEL_DOWNLOAD_DIRECTORY/$KERNEL_INSTALL_DIRECTORY"

	echo $LINE
	echo "${S}Transferring kernel/module debs to kernel install directory: ${C}$installDirectory${N}"
	cp /var/cache/apt/archives/*${kernelBase}*.deb $installDirectory 2>/dev/null
	echo "${S}Kernel/module debs transferred.${N}"
	eval $LOGUE
}

###---------------------------------------------------------------------
### kernel install using zip files
###---------------------------------------------------------------------

install_kernel_zip()
{
	eval $LOGPS
	local FullFileName='' skipWget='' proceedNormally=0 # default: true
	local installKernel='install-kernel.sh'
	local kernelFailed='' download3Failed='' kernelBase='' kbuildKernel=''

	create_kernel_install_directory $KERNEL_FILE
	proceedNormally="$?" # 0 for mv/rm, 1 for use, 2 for use no unzip
	if [ "$proceedNormally" -gt 0 ];then
		skipWget='true'
	fi

	# build the name of the kernel file to download and test for
	FullFileName=$KERNEL_FILE$KZ

	if [ "$skipWget" != 'true' ];then
		# download the kernel, and see if any error occured as well
		download_kernel $FullFileName
		# this is an awkward way to get the test back into true/false form
		download3Failed="$?"
		# return of 1 triggers failed true flag
		if [ "$download3Failed" -gt 0 ];then
			download3Failed='true'
		fi
	fi

	if [ ! -f $FullFileName ];then
		error_handler 'kernel-download-failed' $FUNCNAME
	else
		# careful with the logic here, it's only in the case where the final download failed
		# flag is not set that we will count the download as a success
		# run a cyclic redundancy check on the zip file first
		echo "${S}Testing integrity of downloaded kernel zip installer file ${C}$FullFileName${S}...${N}"
		unzip -t $FullFileName &> /dev/null || error_handler 'kernel-zip-corrupted' $FUNCNAME $FullFileName
		echo "${S}Kernel zip installer file is fine, continuing...${N}"
		backup_grub
		# this is the slh fix for future kernel stuff
		grep -q '  */sbin/update-grub$' /etc/kernel-img.conf 2> /dev/null && sed -i 's%=.*sbin/update-grub%= update-grub%' /etc/kernel-img.conf

		if [ "$proceedNormally" -lt 2 ];then
			unzip -q $FullFileName
		fi

		if [ -f $installKernel ];then
			# if there's a kbuild to be installed then let's install it, have to be careful
			# with different kernel names, this should get them all
			kernelBase=$( cut -d '-' -f 1 <<< $KERNEL_FILE | cut -d '.' -f 1-3 )
			kbuildKernel="linux-kbuild-$kernelBase"
			# anymore but leaving it for now
			if [ -n "$( check_package_status $kbuildKernel 'c' )" -a -z "$( check_package_status $kbuildKernel 'i' )" ];then
				package_installer "$kbuildKernel" 'install-missing'
			fi
			# then we force the libc6 stuff to get installed
			# this is set top of smxi file, to make turning off this feature easier.
			if [ "$B_LIBC6_BORKED" != 'true' ];then
				libc6_fix_1 'kernel'
			fi
			echo $LINE
			echo "${S}Starting your kernel install now...${N}"
			if [ ! -x $installKernel ];then
				chmod +x $installKernel
			fi
			libata_devicemap_fix_1 # run this right before in case something borked above
			./$installKernel || kernelFailed="$?"
			if [ -n "$kernelFailed" ];then
				error_handler 'kernel-zip-install-failed' $FUNCNAME "$kernelFailed"
			else
				post_kernel_install_steps
			fi
		else
			error_handler 'kernel-zip-installer-missing' $FUNCNAME
		fi
	fi
	eval $LOGPE
}

# args: $1 - full Kernel file Name
download_kernel()
{
	eval $LOGUS
	local FullFileName=$1 kernelDownloadPath=''
	local downloadFailed=''
	local ua="-U s-tools/kernels.$FullFileName"

	# now we'll grab the kernel zip file from home base
	wget $ua -T$TIME_OUT -t2 -Nc $SCRIPT_DOWNLOAD_KERNELS$BITS'/'$FullFileName || downloadFailed='true'

	if [ "$downloadFailed" == 'true' ];then
		echo "${E}The default kernel download location: ${C}$SCRIPT_DOWNLOAD_KERNELS"
		echo "${E}could not be accessed, or it doesn't have the kernel you requested."
		echo
		echo "${S}If kernel has not been previously downloaded here, the script will exit.${N}"
		eval $LOGUE
		# create return values
		return 1 # 1 on error, that is
	else
		eval $LOGUE
		return 0 # and 0 for success, as normal for bash
	fi
}

post_kernel_install_steps()
{
	eval $LOGPS
	local realKernelVersion=$( get_real_kernel_version )

	echo $LINE
	echo "${S}Your kernel installation appears to have been successful!"
	echo "Running some post install steps now for you...${N}"
	# run through the link and initrd.img checks to make sure
	update_kernel_links $realKernelVersion
	# let's update grub to make sure it's all good
	update_grub
	# not running this yet
	# extra_module_installer  $realKernelVersion 'madwifi'
	# extra_module_installer  $realKernelVersion 'ndiswrapper'
	cd $SCRIPT_HOME # make sure we are back 
	post_install_messages
	# then we're ready to reboot
	reboot_now_question $realKernelVersion
	eval $LOGPE
}

get_real_kernel_version()
{
	eval $LOGUS
	# we need to first extract the new naming schema:
	local installKernel='install-kernel.sh'
	local	installFile="$SM_KERNEL_DOWNLOAD_DIRECTORY/$KERNEL_INSTALL_DIRECTORY/$installKernel"
	local kTest1=$( grep '^K_UPSTREAM=' $installFile | cut -d '"' -f 2 )
	local kTest2=$( grep '^K_ABINAME=' $installFile | cut -d '"' -f 2 )
	# we don't always know when the VER has "" in it
	local kTest3=$( grep '^VER=' $installFile | cut -d '=' -f 2 | cut -d '"' -f 2 | grep '2.6' )
	local kTest4=$( grep '^KERNEL_VERSION=' $installFile | cut -d '=' -f 2 | cut -d '"' -f 2 | grep -Es '^(2\.6|[3-9])' )
	local kTestError='' kernelString=''

	if [ -n "$kTest1" -a -n "$kTest2" ];then
		kernelString="$kTest1-$kTest2"
	elif [ -n "$kTest3" ];then
		kernelString=$kTest3
	elif [ -n "$kTest4" ];then
		kernelString=$kTest4
	else
		kernelString='kernel-version-test-error-true'
	fi
	# return the string value
	echo $kernelString
	log_function_data "kernelString: $kernelString"
	eval $LOGUE
}

###---------------------------------------------------------------------
### kernel utilities
###---------------------------------------------------------------------

# this is a temp fix to handle the break in libata kernel installs as of 2.6.25.11
libata_devicemap_fix_1()
{
	eval $LOGUS
	local dMap='/boot/grub/device.map'
	local isHdx=$( grep '/dev/hd' $dMap )

	if [ -n "$isHdx" ];then
		echo $LINE
		echo "${S}Updating ${C}$dMap${S} to change all /dev/hdx to /dev/sdx...${N}"
		sed -i 's|/dev/hd|/dev/sd|' $dMap
	fi
	eval $LOGUE
}

# just in case we'll confirm this here
# args: $1 installing kernel
update_kernel_links()
{
	eval $LOGUS
	local uir='' installKernel=$1

	if [ -n "$1" ];then # protect here to avoid major errors
		echo $LINE
		# we do need an initrd
		if [ ! -f "/boot/initrd.img-${installKernel}" ];then
			echo "${S}Creating a missing ${C}initrd.img${S} now...${N}"
			update-initramfs -c -k "${installKernel}"
		else
			echo "${S}Updating ${C}initrd.img${S} to make sure it's all fine...${N}"
			update-initramfs -u -k "${installKernel}"
		fi

		echo "${S}Updating kernel ${C}vmlinuz/initrd.img${S} links...${N}"
		#echo "${S}Removing ${C}/boot${S} links...${N}"
		if [ -L /boot/vmlinuz ];then
			rm -f /boot/vmlinuz
		fi
		if [ -L /boot/initrd.img ];then
			rm -f /boot/initrd.img
		fi
		if [ -L /boot/System.map ];then
			rm -f /boot/System.map
		fi


# 		if [ -L /boot/vmlinuz ];then
# 			ln -fs "vmlinuz-${installKernel}" /boot/vmlinuz
# 		fi
# 		if [ -L /boot/initrd.img ];then
# 			ln -fs "initrd.img-${installKernel}" /boot/initrd.img
# 		fi
# 		if [ -L /boot/System.map ];then
# 			ln -fs "System.map-${installKernel}" /boot/System.map
# 		fi


		if [ -L /vmlinuz ];then
			ln -fs "boot/vmlinuz-${installKernel}" /vmlinuz
		fi
		# set new kernel as default
		if [ -L /initrd.img ];then
			ln -fs "boot/initrd.img-${installKernel}" /initrd.img
		fi

		# set symlinks to the kernel headers
		ln -fs "linux-headers-${installKernel}" /usr/src/linux >/dev/null 2>&1
	else
		error_handler 'value-null' $FUNCNAME '$1'
	fi
	eval $LOGUE
}

update_grub()
{
	eval $LOGUS
	if [ -f $GRUB_PATH ];then # handles cases where user might have lilo
		echo $LINE
		echo "${S}Running ${C}update-grub${S}...${N}"
		update-grub
		echo "${C}update-grub${S} completed.${N}"
	fi
	eval $LOGUE
}

backup_grub()
{
	eval $LOGUS
	if [ "$B_GRUB_2" != 'true' ];then
		echo $LINE
		echo "${S}Backing up ${C}$GRUB_PATH"
		if [ ! -f $GRUB_BU_PATH ];then
			cp $GRUB_PATH $GRUB_BU_PATH
			echo "${S}Your backup file is here: ${C}$GRUB_BU_PATH${S}.${N}"
		else
			echo "${E}You have already created a backup copy of ${C}$GRUB_PATH${E} today."
			echo "${S}The backup copy is found here: ${C}$GRUB_BU_PATH${S}.${N}"
		fi
	fi
	eval $LOGUE
}

post_install_messages()
{
	eval $LOGUS
	local driverReinstall=$( nonfree_driver_reinstall 'kernel-install' )
	# note: latino idea: m-a --text-mode --non-inter -l "${VER}" a-i fglrx
	if [ -n "$driverReinstall" ];then
		echo $MLINE
		echo "${W}WARNING:${M} You must reinstall your ${C}$driverReinstall${M} driver after each kernel upgrade."
		echo "X/Kde will not work until you reinstall your ${C}$driverReinstall${M} driver."
		echo
		if [ "$B_GUI_MODE" != 'true' -a "$driverReinstall" != 'ATI/fglrx' ];then
			echo "${S}You can reinstall the driver to your new kernel now using ${C}$SCRIPT_NAME${S} (continue, do not exit script),"
			echo "or you can do it manually, with ${C}sgfxi -K <your new kernel name> <other  options>${S}${N}"
		else
			echo "${S}You will need to reboot in order to reinstall the ${C}$driverReinstall${S} driver to your new kernel.${N}"
		fi
		print_hec
	fi
	eval $LOGUE
}

# args: $1 - which kernel was installed; $2 - non free info
reboot_now_question()
{
	eval $LOGPS
	local driverReinstall=$( nonfree_driver_reinstall 'kernel-install' )
	local continueOpt='' nonfreeText='' altText2='' altText1='' altText3=''
	local altText4="$DU_UPGRADE and system maintainance"
	
	if [ "$B_GUI_MODE" == 'true' ];then
		altText4='system maintainance'
		altText1="Return to main option selector, skip reboot for now."
		continueOpt='return-main-option-selector'
	fi
	if [ -n "$driverReinstall" ];then
		if [ "$B_GUI_MODE" == 'true' ];then
			nonfreeText='echo -e "\n${M}Since you are running ${C}$SCRIPT_NAME${M} in ${C}Gui/X ${M}mode, you cannot reinstall your\n${C}$driverReinstall${M} graphics driver in X. You will need to reinstall\nthat out of X, either now, or when you reboot."'
			altText3="${M}You are running in ${C}X${M}: you must leave ${C}X${M} to install your non-free graphics driver: ${C}$driverReinstall${S}\n"
		else
			continueOpt='continue-reinstall-graphics-driver'
			if [ "$B_NVIDIA" == 'true' ];then
				nonfreeText='echo -e "\n${M}When you are finished reinstalling your ${C}$driverReinstall${S} graphics driver, the script\nwill give you the option to reboot into your new kernel."'
				altText2='echo -e "${M}NEW!${S} If you continue, you can finish up the $DU_UPGRADE, and install ${C}$driverReinstall${S} graphics\ndrivers to your new kernel ${C}$1${S} without rebooting first.\n"'
				altText1="Proceed to $DU_UPGRADE / $driverReinstall graphics\n   driver re-install and other ${C}$SCRIPT_NAME${S} functions."
				altText3="${M}Install nvidia drivers before you reboot if required${S}\n"
			else
				altText1="Proceed to $DU_UPGRADE and other ${C}$SCRIPT_NAME${S} functions."
				altText2='echo -e "${S}If you continue, you can finish up the $DU_UPGRADE and other options before rebooting.\n'$altText3'"'
				altText3="${M}You must reboot into your new kernel to install fglrx drivers.${S}\n"
			fi
		fi
	else
		# note this will just trigger if no nvidia driver was installed to begin with
		if [ "$B_GUI_MODE" == 'true' ];then
			altText2='echo -e "${S}If you continue, you can finish up the system maintenance before rebooting.\n'$altText3'"'
		else
			continueOpt='continue'
			altText1="Proceed to $DU_UPGRADE and other ${C}$SCRIPT_NAME${S} functions."
			altText2='echo -e "${S}If you continue, you can finish up the $DU_UPGRADE and other options before rebooting.\n'$altText3'"'
			if [ "$B_NVIDIA" == 'true' ];then
				altText3="${M}Feature: install nvidia drivers before you reboot if required${S}\n"
			elif "$B_ATI" == 'true' ];then
				altText3="${M}You must reboot into your new kernel to install fglrx drivers.${S}\n"
			fi
		fi
	fi

	local repeat='' options="reboot-now $continueOpt quit"

	cd $SCRIPT_HOME # needed to make sure user is back in correct directory
	# sets B_KERNEL_EQUAL_INSTALL
	test_kernel_strings "$1" 'set-ke'

	echo $MLINE
	echo "${M}KERNEL INSTALL COMPLETE"
	echo $MLINE
	log_function_data "B_KERNEL_EQUAL_INSTALL: $B_KERNEL_EQUAL_INSTALL"

	if [ "$B_KERNEL_EQUAL_INSTALL" != 'true' ];then
		eval $altText2
		echo "${S}If you're all done, and just want to start your new kernel, then just reboot now."
		eval $nonfreeText
		echo $LINE
		echo "${C}1 - reboot-now${S} Reboot system now to start new kernel, if you are all done"
		echo "    with your $altText4."
		echo -e "${C}2 - $continueOpt${S} $altText1"
		echo "${C}3 - quit${S} Exit script now."

		echo $LINE
		echo -e $SLE
		echo $LINE

		select opt in $options
		do
			case $opt in
				reboot-now)
					echo $LINE
					echo "${S}Rebooting now into your new ${C}$1${S} kernel...${N}"
					eval $LOGPE
					handle_shutdowns 'reboot'
					exit 0
					;;
				$continueOpt)
					echo "${S}Continuing on to finish your system maintenance."
					echo "${M}Remember your new kernel will not be active until you reboot.${N}"
					KERNEL_INSTALL_TO=$1
					log_function_data "KERNEL_INSTALL_TO: $KERNEL_INSTALL_TO"
					;;
				quit)
					echo "${M}Ok, but remember your kernel is not active yet until you reboot.${N}"
					print_quit
					;;
				*)
					print_error opt
					repeat='true'
					;;
				esac
			break
		done
		eval $LOGPS
		if [ "$repeat" == 'true' ];then
			reboot_now_question "$1"
		fi
	else
		echo "${M}You appear to have reinstalled your running kernel for some reason. That's fine, "
		echo "although you may want to reboot anyway to make sure it's all working right."
		echo $LINE
		echo "${S}Feel free to continue on doing things in ${C}$SCRIPT_NAME${S} if you want.${N}"
		print_hec
		eval $LOGPS
	fi
}

# args: $1 - $KERNEL_FILE/installed kernel
create_kernel_install_directory()
{
	eval $LOGUS
	local directoryAction=0

	KERNEL_INSTALL_DIRECTORY=$1
	log_function_data "KERNEL_INSTALL_DIRECTORY: $KERNEL_INSTALL_DIRECTORY"
	echo $LINE
	echo "${S}Please note!! The kernel install directory will be located here:"
	echo "${C}$SM_KERNEL_DOWNLOAD_DIRECTORY/$KERNEL_INSTALL_DIRECTORY${N}"
	# create and move to the primary storage directory for kernel downloads
	if [ ! -d $SM_KERNEL_DOWNLOAD_DIRECTORY ];then
		mkdir $SM_KERNEL_DOWNLOAD_DIRECTORY
	fi
	cd $SM_KERNEL_DOWNLOAD_DIRECTORY
	# here the script wil create a directory named with the current kernel name
	if [ ! -d $KERNEL_INSTALL_DIRECTORY ];then
		mkdir $KERNEL_INSTALL_DIRECTORY
	else
		# set whether to wget file or not, only happens if already downloaded
		handle_preexisting_install_directory $KERNEL_INSTALL_DIRECTORY
		directoryAction="$?" # 0 for mv/rm, 1 for use, 2 for use no unzip
	fi
	cd $SM_KERNEL_DOWNLOAD_DIRECTORY/$KERNEL_INSTALL_DIRECTORY
	eval $LOGUE
	return $directoryAction
}

# args: $1 which directory
handle_preexisting_install_directory()
{
	eval $LOGUS
	local opt=''
	local olddirectory=$SM_KERNEL_DOWNLOAD_DIRECTORY/$1
	local newdirectory="$olddirectory-$(date +%y-%m-%d)"
	local options='delete-directory rename-directory use-directory use-directory-no-unzip quit'
	echo $ELINE
	echo "${E}There is already a ${C}$KERNEL_INSTALL_DIRECTORY${S} directory present in your system!"
	echo $ELINE
	echo "${S}Either you are trying to install a kernel you already have on your system,"
	echo "or you created this directory yourself. You have the following options:"
	echo $LINE
	echo "${C}1 - delete-directory${S} - Script deletes directory: ${C}$olddirectory"
	echo "${C}2 - rename-directory${S} - Script renames existing directory to: ${C}$newdirectory"
	echo "${C}3 - use-directory${S} - Uses this directory, and assumes it has the kernel"
	echo "    zip file in it already, but not yet unzipped."
	echo "${C}4 - use-directory-no-unzip${S} - Uses this directory, and assumes the kernel"
	echo "    downloaded kernel zip file has already been unzipped."
	echo
	echo "${C}5 - exit${S} - Quit now, I'll check this myself then start the script again."
	echo $LINE
	echo $SLE
	echo $LINE

	select opt in $options
	do
		case $opt in
			delete-directory)
				echo "${S}Deleting this directory: ${C}$olddirectory"
				rm -f -r $olddirectory
				echo "${C}$olddirectory${S} has been removed. Continuing with kernel install.${N}"
				mkdir $olddirectory
				echo "${S}Created new empty directory: ${C}$olddirectory${N}"
				eval $LOGUE
				return 0
				;;
			rename-directory)
				echo "${S}Renaming this directory: ${C}$olddirectory"
				echo "To this backup name: ${C}$newdirectory${N}"
				mv $olddirectory $newdirectory
				echo "${S}Directory renamed"${N}
				mkdir $olddirectory
				echo "${S}Created new empty directory: ${C}$olddirectory${N}"
				eval $LOGUE
				return 0
				;;
			use-directory)
				echo "${M}Ok, using the current install directory: ${C}$olddirectory"
				echo "${S}Hopefully it contains the kernel download zip file.${N}"
				eval $LOGUE
				return 1
				;;
			use-directory-no-unzip)
				echo "${M}Ok, using the current install directory:  ${C}$olddirectory"
				echo "without unzipping kernel file.${N}"
				eval $LOGUE
				return 2
				;;
			quit)
				print_quit
				;;
			*)
				print_error yn
				handle_preexisting_install_directory $1
				;;
		esac
	done
}

# small utility just so we have the list in one place for all
# functions that will use it, this will be used for looping type
# stuff re module installer options.
print_module_list()
{
	eval $LOGUS

	# lirc-modules-
	local availableModules="
	acer-acpi-modules-
	acerhk-modules-
	atl2-modules-
	aufs-modules-
	btrfs-modules-
	drbd8-modules-
	eeepc-acpi-modules-
	em8300-modules-
	et131x-modules-
	fsam7400-modules-
	gspca-modules-
	kqemu-modules-
	lirc-modules-modules-
	loop-aes-modules-
	lzma-modules-
	ndiswrapper-modules-
	nilfs-modules-
	omnibook-modules-
	qc-usb-modules-
	r5u870-modules-
	r6040-modules-
	rfswitch-modules-
	rt73-modules-
	sfc-modules-
	speakup-modules-
	squashfs-modules-
	tp-smapi-modules-
	virtualbox-ose-guest-modules-
	virtualbox-ose-modules-
	"

	echo "$availableModules"
	eval $LOGUE
}
# args: $1 kernel install version; $2 - which module madwifi/ndiswrapper
extra_module_installer()
{
	eval $LOGUS
	local kernelVersion=$1 moduleName=$2 argMissing='' driverTest=''
	local filename='' tarball='' module='' message='' extra='' buildFailed=0
	local moduleSourcePresent='' modulePackage=''

	case $moduleName in
		madwifi)
			filename='ath_pci'
			tarball='madwifi.tar.bz2'
			module='madwifi'
			message="Atheros Wireless Network Adaptor will not work until\nthe non-free madwifi driver is reinstalled."
			extra='Atheros '
			moduleSourcePresent=$( check_package_status 'madwifi-source' 'c' )
			;;
		ndiswrapper)
			filename='ndiswrapper'
			tarball='ndiswrapper.tar.bz2'
			module='ndiswrapper'
			message="Wireless Network Adaptor using ndiswrapper will not work\nuntil the ndiswrapper module is reinstalled."
			moduleSourcePresent=$( check_package_status 'ndiswrapper-source' 'c' )
			;;
		*)
			error_handler 'value-bad' $FUNCNAME "$moduleName"
			;;
	esac
	echo $LINE
	echo "${S}Checking ${C}$module${S} status now...${N}"
	# note: etch doesn't support -k option but that's ok, it will soon be lenny
	driverTest=$( /sbin/modinfo -k $CURRENT_KERNEL -F filename $filename 2>/dev/null )
	
	# hints for module to be built
	if [ -n "$1" -a -n "$2" ];then
		#/sbin/modinfo -k $CURRENT_KERNEL -F filename $filename 2>/dev/null 2>&1
		if [ -n "$driverTest" ];then
			# this is a slow test so only run if needed
			modulePackage="$( dpkg -S $driverTest 2>/dev/null | grep -iv 'linux-image-' )"
			if [ -n "$modulePackage" ];then
				if [ -n "$moduleSourcePresent" ];then
		# 			echo "${S}Checking to see if ${C}$extra$module${S} can be built for your wifi card...${N}"
		# 			if [ -f /usr/src/${tarball} ] && which m-a >/dev/null
		# 			then
					echo "${S}Starting build of your ${C}$module${S} module now...${N}"
					# user setup madwifi with module-assistant already
					# we may as well do that for him again now
					if [ -d /usr/src/modules/${module}/ ];then
						rm -rf /usr/src/modules/${module}/
					fi
					# this will pull in the source if required etc...
					m-a --text-mode --non-inter -l $kernelVersion a-i $module || buildFailed=$?
		# 			else
					if  [ "$buildFailed" -eq 249 ];then # this is pre-exisisting module error
						echo $MLINE
						echo "${C}error 249${M} just means ${C}$module${M} was already installed on your new kernel. "
						echo "Sometimes ${C}$SCRIPT_NAME${M} and the current apt kernel installers"
						echo "might be slightly out of sync, that's ok though.${N}"
					elif [ "$buildFailed" -gt 0 ];then
						echo $WLINE
						echo "${E}The ${C}m-a${E} build of your module exited with error code ${C}$buildFailed${S}"
						echo -e "$message"
						echo
						echo "Please report any critical errors you might get on $SCRIPT_NAME forums,"
						echo "especially the exit error number.${S}"
						echo $WLINE
						print_hec
					fi
				else
					echo $ELINE
					echo "${E}There is no ${C}$module-source${E} package for ${C}$module${E} available in apt."
					echo "${S}Cannot build your module using ${C}m-a${S}, sorry.${N}"
					print_hec
				fi
			fi
		fi
	else
		if [ -z "$1" ];then
			argMissing='$1 '
		fi
		if [ -z "$2" ];then
			argMissing=$argMissing'$2'
		fi
		error_handler 'value-null' $FUNCNAME "$argMissing"
	fi
	eval $LOGUE
}


###**EOF**###